import pygame
import random
import sys

# 初始化pygame
pygame.init()

# 设置窗口大小和布局
TOP_PANEL_HEIGHT = 50  # 控制面板的高度
CELL_SIZE = 40
ROWS, COLS = 10, 10
MINES = 10
WIDTH, HEIGHT = COLS * CELL_SIZE, ROWS * CELL_SIZE + TOP_PANEL_HEIGHT
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('扫雷')

# 设置颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BACKGROUND_COLOR = (192, 192, 192)  # 深灰色背景
HIGHLIGHT_COLOR = (200, 200, 200)
SHADOW_COLOR = (100, 100, 100)

# 定义更多颜色
BLUE = (10, 10, 255)
GREEN = (10, 128, 10)
RED = (255, 10, 10)
PURPLE = (128, 10, 128)
ORANGE = (255, 165, 10)
CYAN = (10, 255, 255)
YELLOW = (255, 255, 10)

# 定义笑脸按钮的尺寸
FACE_BUTTON_SIZE = (32, 32)

# 加载并缩放笑脸图片到适当的尺寸
FACE_HAPPY_PATH = r"D:\Coding\Project\minesweeper_py\happyface.png"  # 替换为实际路径
FACE_OOPS_PATH = r"D:\Coding\Project\minesweeper_py\oppsface.png"  # 替换为实际路径
FACE_HAPPY = pygame.transform.scale(pygame.image.load(FACE_HAPPY_PATH), FACE_BUTTON_SIZE)
FACE_OOPS = pygame.transform.scale(pygame.image.load(FACE_OOPS_PATH), FACE_BUTTON_SIZE)

# 加载旗帜和地雷图标
flag_image = pygame.image.load(r"D:\Coding\Project\minesweeper_py\flag.png")  # 替换为实际路径
mine_image = pygame.image.load(r"D:\Coding\Project\minesweeper_py\mine.png")  # 替换为实际路径

# 添加新的状态变量
GAME_STATE_PLAYING = 0
GAME_STATE_WIN = 1
GAME_STATE_LOSE = 2
game_state = GAME_STATE_PLAYING

# 创建棋盘和地雷
def create_board():
    board = [[0 for _ in range(COLS)] for _ in range(ROWS)]
    mines = set()
    while len(mines) < MINES:
        x = random.randint(0, ROWS - 1)
        y = random.randint(0, COLS - 1)
        if (x, y) not in mines:
            mines.add((x, y))
    return board, mines

# 更新棋盘上的地雷数
def update_board(board, mines):
    for x, y in mines:
        for i in range(max(0, x-1), min(ROWS, x+2)):
            for j in range(max(0, y-1), min(COLS, y+2)):
                if (i, j) not in mines:
                    board[i][j] += 1

# 揭示区域
def reveal_area(board, x, y, revealed):
    if (x, y) not in revealed:
        revealed.add((x, y))
        if board[x][y] == 0:
            for i in range(max(0, x-1), min(ROWS, x+2)):
                for j in range(max(0, y-1), min(COLS, y+2)):
                    if (i, j) not in revealed:
                        reveal_area(board, i, j, revealed)

# 揭示整个棋盘
def reveal_board(board, revealed, mines):
    for i in range(ROWS):
        for j in range(COLS):
            if (i, j) not in revealed and (i, j) in mines:
                revealed.add((i, j))

# 绘制顶部控制面板
def draw_top_panel(mines_left, elapsed_time):
    screen.fill(BACKGROUND_COLOR)
    font = pygame.font.SysFont(None, 36)

    # 地雷计数器
    mines_text = font.render(f"Mines: {mines_left}", True, BLACK)
    screen.blit(mines_text, (10, 10))

    # 计时器
    time_text = font.render(f"Time: {elapsed_time}s", True, BLACK)
    screen.blit(time_text, (WIDTH - time_text.get_width() - 10, 10))

    # 笑脸按钮
    face_img = FACE_HAPPY if game_state == GAME_STATE_PLAYING else FACE_OOPS
    screen.blit(face_img, ((WIDTH - face_img.get_width()) // 2, 10))

# 绘制棋盘
def draw_board(board, revealed, flagged):
    for x in range(ROWS):
        for y in range(COLS):
            cell_x = y * CELL_SIZE
            cell_y = x * CELL_SIZE + TOP_PANEL_HEIGHT

            if (x, y) not in revealed:
                # 绘制未揭示的方块，带有高光和阴影
                pygame.draw.rect(screen, HIGHLIGHT_COLOR, (cell_x, cell_y, CELL_SIZE, 1))  # Top highlight
                pygame.draw.rect(screen, HIGHLIGHT_COLOR, (cell_x, cell_y, 1, CELL_SIZE))  # Left highlight
                pygame.draw.rect(screen, SHADOW_COLOR, (cell_x, cell_y + CELL_SIZE - 1, CELL_SIZE, 1))  # Bottom shadow
                pygame.draw.rect(screen, SHADOW_COLOR, (cell_x + CELL_SIZE - 1, cell_y, 1, CELL_SIZE))  # Right shadow
                pygame.draw.rect(screen, (160, 160, 160), (cell_x + 1, cell_y + 1, CELL_SIZE - 2, CELL_SIZE - 2))
            else:
                # 绘制揭示后的方块，颠倒高光和阴影
                pygame.draw.rect(screen, SHADOW_COLOR, (cell_x, cell_y, CELL_SIZE, 1))  # Top shadow
                pygame.draw.rect(screen, SHADOW_COLOR, (cell_x, cell_y, 1, CELL_SIZE))  # Left shadow
                pygame.draw.rect(screen, HIGHLIGHT_COLOR, (cell_x, cell_y + CELL_SIZE - 1, CELL_SIZE, 1))  # Bottom highlight
                pygame.draw.rect(screen, HIGHLIGHT_COLOR, (cell_x + CELL_SIZE - 1, cell_y, 1, CELL_SIZE))  # Right highlight
                color = BACKGROUND_COLOR
                pygame.draw.rect(screen, color, (cell_x + 1, cell_y + 1, CELL_SIZE - 2, CELL_SIZE - 2))

                if board[x][y] > 0:
                    font = pygame.font.SysFont(None, 24)
                    color_map = {1: BLUE, 2: GREEN, 3: RED, 4: PURPLE, 5: ORANGE, 6: CYAN, 7: YELLOW, 8: BLACK}
                    text_color = color_map.get(board[x][y], BLACK)
                    text = font.render(str(board[x][y]), True, text_color)
                    screen.blit(text, (cell_x + CELL_SIZE//2 - text.get_width()//2, cell_y + CELL_SIZE//2 - text.get_height()//2))
                elif (x, y) in mines:
                    mine_img = pygame.transform.scale(mine_image, (CELL_SIZE, CELL_SIZE))
                    screen.blit(mine_img, (cell_x, cell_y))
            if (x, y) in flagged:
                flag_img = pygame.transform.scale(flag_image, (CELL_SIZE, CELL_SIZE))
                screen.blit(flag_img, (cell_x, cell_y))

def on_left_click(x, y):
    global game_state
    if (x, y) in revealed or (x, y) in flagged:
        return
    if (x, y) in mines:
        reveal_board(board, revealed, mines)
        game_state = GAME_STATE_LOSE
    else:
        reveal_area(board, x, y, revealed)
        check_win()

def on_right_click(x, y):
    if (x, y) in revealed:
        return
    if (x, y) in flagged:
        flagged.remove((x, y))
    else:
        flagged.add((x, y))

def check_win():
    global game_state
    cells_revealed = len(revealed)
    total_cells = ROWS * COLS
    if cells_revealed == total_cells - MINES:
        print("You win!")
        game_state = GAME_STATE_WIN

def draw_popup(message, button_texts):
    global game_state
    # 创建半透明背景
    overlay = pygame.Surface((WIDTH, HEIGHT))
    overlay.set_alpha(150)
    overlay.fill(BACKGROUND_COLOR)
    screen.blit(overlay, (0, 0))

    # 创建消息框
    font = pygame.font.SysFont(None, 48)
    text = font.render(message, True, BLACK)
    text_rect = text.get_rect(center=(WIDTH//2, HEIGHT//2 - 70))  # 调整消息框位置
    
    # 绘制消息文本
    screen.blit(text, text_rect)

    # 定义按钮属性
    btn_padding = 20  # 内边距
    btn_spacing = 30  # 按钮之间的间距
    btn_height = 60   # 按钮的高度

    # 计算按钮总宽度（所有按钮加起来）
    total_btn_width = sum([pygame.font.SysFont(None, 36).render(btn_text, True, WHITE).get_width() + btn_padding * 2 for btn_text in button_texts]) + btn_spacing * (len(button_texts) - 1)

    # 计算每个按钮的位置
    start_x = WIDTH // 2 - total_btn_width // 2  # 所有按钮组的起始x坐标
    current_x = start_x

    buttons = []
    for i, btn_text in enumerate(button_texts):
        btn_font = pygame.font.SysFont(None, 36)
        btn_text_surface = btn_font.render(btn_text, True, WHITE)
        btn_width = btn_text_surface.get_width() + btn_padding * 2  # 增加宽度以适应内边距

        btn_rect = pygame.Rect(current_x, HEIGHT // 2 + 20, btn_width, btn_height)

        # 绘制按钮的顶部和左侧高光
        pygame.draw.rect(screen, HIGHLIGHT_COLOR, (btn_rect.left, btn_rect.top, btn_width, 9))  # Top highlight
        pygame.draw.rect(screen, HIGHLIGHT_COLOR, (btn_rect.left, btn_rect.top, 9, btn_height))  # Left highlight

        # 绘制按钮的底部和右侧阴影
        pygame.draw.rect(screen, SHADOW_COLOR, (btn_rect.left, btn_rect.bottom - 9, btn_width, 9))  # Bottom shadow
        pygame.draw.rect(screen, SHADOW_COLOR, (btn_rect.right - 9, btn_rect.top, 9, btn_height))  # Right shadow

        # 绘制按钮主体
        button_color = BLUE if i == 0 else RED
        pygame.draw.rect(screen, button_color, btn_rect)

        # 绘制按钮上的文字
        screen.blit(btn_text_surface, btn_rect.move(btn_padding, btn_height // 2 - btn_text_surface.get_height() // 2))

        buttons.append(btn_rect)

        # 更新下一个按钮的起始位置
        current_x += btn_width + btn_spacing

    return buttons

def check_popup_click(buttons):
    global game_state, board, mines, revealed, flagged, start_time
    mx, my = pygame.mouse.get_pos()
    for i, btn_rect in enumerate(buttons):
        if btn_rect.collidepoint(mx, my):
            if i == 0:  # 再来一局按钮被点击
                game_state = GAME_STATE_PLAYING
                board, mines = create_board()
                update_board(board, mines)
                revealed.clear()
                flagged.clear()
                start_time = pygame.time.get_ticks()
            elif i == 1:  # 退出按钮被点击
                pygame.quit()
                sys.exit()

board, mines = create_board()
update_board(board, mines)
revealed = set()
flagged = set()

# 计时器初始化
start_time = pygame.time.get_ticks()

running = True
while running:
    current_time = pygame.time.get_ticks()
    elapsed_time = (current_time - start_time) // 1000  # 秒

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN and game_state == GAME_STATE_PLAYING:
            mx, my = event.pos
            x, y = (my - TOP_PANEL_HEIGHT) // CELL_SIZE, mx // CELL_SIZE
            if 0 <= x < ROWS and 0 <= y < COLS and my >= TOP_PANEL_HEIGHT:
                if event.button == 1:  # 左键点击
                    on_left_click(x, y)
                elif event.button == 3:  # 右键点击
                    on_right_click(x, y)
            elif event.button == 1 and 10 <= mx <= WIDTH - 10 and 10 <= my <= TOP_PANEL_HEIGHT - 10:
                # 如果点击了笑脸，重新开始游戏
                board, mines = create_board()
                update_board(board, mines)
                revealed.clear()
                flagged.clear()
                game_state = GAME_STATE_PLAYING
                start_time = current_time
        elif event.type == pygame.MOUSEBUTTONDOWN and game_state != GAME_STATE_PLAYING:
            buttons = draw_popup("You win!" if game_state == GAME_STATE_WIN else "Game Over!", ["Again", "Exit"])
            check_popup_click(buttons)

    if game_state == GAME_STATE_PLAYING:
        draw_top_panel(MINES - len(flagged), elapsed_time)
        draw_board(board, revealed, flagged)
    else:
        buttons = draw_popup("You win!" if game_state == GAME_STATE_WIN else "Game Over!", ["Again", "Exit"])
    
    pygame.display.flip()
    pygame.time.Clock().tick(60)

pygame.quit()
sys.exit()